package Proxy;

import cong.cheng.proxy.JdkProxyFactory;
import cong.cheng.proxy.SmsProxy;
import cong.cheng.proxy.SmsService;
import cong.cheng.proxy.SmsServiceImpl;
import cong.cheng.proxy01.AliSmsService;
import cong.cheng.proxy01.CglibProxyFactory;
import cong.cheng.reflection.TargetObject;
import org.junit.Test;

import java.lang.reflect.Field;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;

public class MyTest01 {

    @Test
    public void test01() throws ClassNotFoundException, NoSuchMethodException, IllegalAccessException,
            InstantiationException, InvocationTargetException, NoSuchFieldException {

        /**
         * 反射
         * */

        /**
         * 获取 TargetObject 类的 Class 对象并且创建 TargetObject 类实例
         */
        Class<?> targetClass = Class.forName("cong.cheng.reflection.TargetObject");
        TargetObject targetObject = (TargetObject) targetClass.newInstance();
        /**
         * 获取 TargetObject 类中定义的所有方法
         */
        Method[] methods = targetClass.getDeclaredMethods();
        for (Method method : methods) {
            System.out.println(method.getName());
        }

        /**
         * 获取指定方法并调用
         */
        Method publicMethod = targetClass.getDeclaredMethod("publicMethod",
                String.class);

        publicMethod.invoke(targetObject, "JavaGuide");

        /**
         * 获取指定参数并对参数进行修改
         */
        Field field = targetClass.getDeclaredField("value");
        //为了对类中的参数进行修改我们取消安全检查
        field.setAccessible(true);
        field.set(targetObject, "JavaGuide");

        /**
         * 调用 private 方法
         */
        Method privateMethod = targetClass.getDeclaredMethod("privateMethod");
        //为了调用private方法我们取消安全检查
        privateMethod.setAccessible(true);
        privateMethod.invoke(targetObject);

    }

    @Test
    public void test02() {
        /**
         * 静态代理
         * 传入需要代理的对象
         * */
        SmsService smsService = new SmsServiceImpl();
        SmsProxy smsProxy = new SmsProxy(smsService);
        smsProxy.send("静态代理");
    }

    @Test
    public void test03(){
        /**
         * JDK动态代理机制
         * 只能代理实现了接口的类或者直接代理接口
         * 自定义 InvocationHandler 并重写invoke方法，
         * 在 invoke 方法中我们会调用原生方法（被代理类的方法）并自定义一些处理逻辑；
         * 通过 Proxy.newProxyInstance(ClassLoader loader,Class<?>[] interfaces,InvocationHandler h) 方法创建代理对象；
         * */
        SmsService smsService = (SmsService) JdkProxyFactory.getProxy(new SmsServiceImpl());
        smsService.send("JDK动态代理");
    }

    @Test
    public void test04(){
        /**
         * CGLIB动态代理机制
         * 可以代理为实现任何接口的类
         * 自定义 MethodInterceptor 并重写 intercept 方法，
         * intercept 用于拦截增强被代理类的方法，和 JDK 动态代理中的 invoke 方法类似；
         * 通过 Enhancer 类的 create()创建代理类
         *
         * */
        AliSmsService aliSmsService = (AliSmsService) CglibProxyFactory.getProxy(AliSmsService.class);
        aliSmsService.send("CGLIB动态代理");
    }

}
